package com.oschina;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import java.util.ArrayList;
import java.util.Random;

public class SimpleRead {
    public SimpleRead() {
        super();
    }

    void connect(String portName) throws Exception {
        //这里根据你传入的 ‘com8’构造一个端口识别器
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        if (portIdentifier.isCurrentlyOwned()) {
            //如果端口被占用则提示
            System.out.println("Error: Port is currently in use");
        } else {
            System.out.println("connection start...");
            CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);

            if (commPort instanceof SerialPort) {//这做判断，如果是串口则执行例子程序。
                //SerialPort是package gnu.io;下的包，就是我们配置的串口识别程序。
                SerialPort serialPort = (SerialPort) commPort;//强制转换成串口。
                //设置串口参数。9600波特率在这里设置。
                serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

                //从串口获得到串口的 输入输出流。
                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();
                //新起一个线程，把刚才获取的in/out传入。然后启动线程
                (new Thread(new SerialReader(in))).start();
                (new Thread(new SerialWriter(out))).start();

            } else {
                //如果不是串口则提示。
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }
    }

    /**
     * 定义一个串口读取类。实现了Runnable接口。
     */
    public static class SerialReader implements Runnable {
        InputStream in;
        InputStreamReader reader;

        /**
         * 构造函数
         *
         * @param in 需要传入一个串口的输入流
         */
        public SerialReader(InputStream in) {
            this.in = in;//获取到输入流实例。
            this.reader = new InputStreamReader(in);
        }

        private void printByte(ArrayList<Byte> result) {
            System.out.println("*************");
            for (int i = 0; i < result.size(); i++) {
                System.out.print(Integer.toHexString(Byte.toUnsignedInt(result.get(i))));
                System.out.print(" ");
            }
            System.out.println();
            System.out.println("*************");
        }

        private void addByte2Array(ArrayList<Byte> result, byte[] target, int len) {
            for (int i = 0; i < len; i++) {
                result.add(target[i]);
            }
        }

        /**
         * java线程启动后执行run方法。
         */
        public void run() {
            byte[] byteBuffer = new byte[6];
            ArrayList<Byte> result = new ArrayList<>();
            int len = 0;
            try {
                //起一个while循环，不断读取端口数据。并把数据写入byteBffer里。
                while ((len = this.in.read(byteBuffer)) > -1) {
                    //print打印出读取的数据。如果是读取的0字节则什么都不打印
                    //System.out.print((new String(byteBuffer, 0, len)));//将byteBuffer转换成字符串。
                    if (len > 0) {
                        addByte2Array(result, byteBuffer, len);
                        printByte(result);
                        if (result.get(result.size() - 1) == Protocol.END) {
                            Protocol.resoveMessage(result.toArray());
                            result.clear();
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 定义一个串口写入类。实现了Runnable接口。
     */
    public static class SerialWriter implements Runnable {
        OutputStream out;

        public SerialWriter(OutputStream out) {
            this.out = out;
        }

        private void writeMessage(byte[] msg) throws IOException {
            System.out.println("写入指令：");
            for (byte aMsg : msg) {
                System.out.print(Integer.toHexString(Byte.toUnsignedInt(aMsg)));
                System.out.print("  ");
                this.out.write(aMsg);
            }
            System.out.println();
        }

        public void run() {
            try {
                int c = 0;
                System.out.println("请输入回车，随机生成指令。（除了2个参数地址闪烁灯的指令）");
                //不断的监听键盘输入事件，如果有输入值则将输入的值写入串口
                while ((c = System.in.read()) > -1) {
                    if (c == 10) {                        //10 代表回车
                        Random r = new Random();
                        int index = r.nextInt(15);

                        //index  随机生成指令序号
                        //Protocol.DIRECTIVE_LIST[index]  向指令集和里查找关键字
                        //Protocol.getSendProtocol    根据关键字生成指令
                        //writeMessage      写入指令
                        writeMessage(Protocol.getSendProtocol(Protocol.DIRECTIVE_LIST[index]));
                    } else {
                        writeMessage(Protocol.getSendProtocol((byte) 0x01, (byte) 0x01));
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
